Skip to content

Leave the sign-up flow when it completes with an assertion - #65

Merged
ThaminduDilshan merged 1 commit into
thunder-id:mainfrom
ZiyamSanthosh:fix/4795-signup-completion-leaves-flow
Aug 11, 2026
Merged

Leave the sign-up flow when it completes with an assertion#65
ThaminduDilshan merged 1 commit into
thunder-id:mainfrom
ZiyamSanthosh:fix/4795-signup-completion-leaves-flow

Conversation

@ZiyamSanthosh

@ZiyamSanthosh ZiyamSanthosh commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Purpose

Fixes a sign-up flow that completes on the server but never finishes in the UI.

When a sign-up completes with an assertion, ThunderIDReactClient.signUp() stores the session and emits sign-in, which is what triggers the /users/me call people have noticed. SignUp.handleComplete then skipped the afterSignUpUrl redirect for exactly those responses:

if (response?.type !== Redirection && afterSignUpUrl && !(response as any)?.assertion) {

The comment justified it as "the SDK stored the session and the caller handled navigation". That premise does not hold for a consumer that passes afterSignUpUrl and no onComplete — the ThunderID Gate sign-up page, for one. Nothing navigated, BaseSignUp.handleSubmit returned without touching currentFlow, and the finished step stayed on screen with a live submit action. Clicking it posted an execute request that began a whole new sign-up flow.

SignIn has no equivalent guard: it always navigates on completion (redirectUrl || afterSignInUrl), so sign-up was the outlier.

Approach

Drop the !assertion condition. A stored session is a reason to leave the flow, not to stay on it. The existing controls still apply: shouldRedirectAfterSignUp is the opt-out for consumers that navigate themselves, and one that passes no afterSignUpUrl is never redirected here.

Redirects are not instantaneous, so the completed step remains interactive for a moment. BaseSignUp now latches the completion and refuses further submissions — the execution id is spent by then, and re-submitting starts a fresh flow.

Display-only completions are untouched: they return before the latch and never reach handleComplete.

Behaviour change worth calling out

A consumer that passes both afterSignUpUrl and onComplete, relying on the assertion case not redirecting, will now be redirected. Setting shouldRedirectAfterSignUp={false} restores the previous behaviour and is the documented way to express "I navigate myself".

Related Issues

Related PRs

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests — new SignUp.test.tsx: a completion carrying an assertion reaches onComplete, and a second submit after completion issues no further flow request.
  • Breaking changes. (Fill if applicable)

Security checks

  • Followed secure coding standards.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Verification

@thunderid/react: 67 tests pass, typecheck clean, no new lint errors on the touched files. Verified manually end to end against a local ThunderID instance with the server side fix applied: the flow completes, /users/me fires as the session hydration step, Gate redirects away, and no trailing execute request is made.

The redirect branch is covered by pointing afterSignUpUrl at a fragment of the current URL, which is a same-document navigation and so observable without the test page reloading. Confirmed the test fails when the !assertion guard is restored.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The sign-up flow now blocks repeated submissions after completion. Non-redirection responses with assertions now redirect to afterSignUpUrl. Tests cover assertion callbacks and duplicate-submission prevention.

Changes

Sign-up completion behavior

Layer / File(s) Summary
Completion latch and submission guard
packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
The component tracks completed flows, marks non-display-only completions, and ignores submissions after completion.
Completion redirect and regression coverage
packages/react/src/components/presentation/auth/SignUp/SignUp.tsx, packages/react/src/components/presentation/auth/SignUp/__tests__/SignUp.test.tsx
Assertion-bearing non-redirection responses redirect to afterSignUpUrl. Tests cover assertion callbacks and duplicate-submission prevention.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: brionmario

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: redirecting the sign-up flow when completion includes an assertion.
Description check ✅ Passed The description covers the purpose, approach, behavior change, related work, tests, security checks, and verification results.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/react/src/components/presentation/auth/SignUp/__tests__/SignUp.test.tsx (1)

65-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for the afterSignUpUrl redirect.

This test disables redirects and only verifies onComplete. It does not execute the changed branch in SignUp.handleComplete.

Add a test with shouldRedirectAfterSignUp={true} and afterSignUpUrl. Verify that an assertion-bearing non-redirection completion navigates to that URL.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/react/src/components/presentation/auth/SignUp/__tests__/SignUp.test.tsx`
around lines 65 - 83, The existing SignUp completion test only verifies
onComplete and does not cover the redirect branch in SignUp.handleComplete. Add
a separate test configuring shouldRedirectAfterSignUp={true} and an
afterSignUpUrl, submit an assertion-bearing non-redirection completion, and
verify navigation occurs to the configured URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@packages/react/src/components/presentation/auth/SignUp/__tests__/SignUp.test.tsx`:
- Around line 65-83: The existing SignUp completion test only verifies
onComplete and does not cover the redirect branch in SignUp.handleComplete. Add
a separate test configuring shouldRedirectAfterSignUp={true} and an
afterSignUpUrl, submit an assertion-bearing non-redirection completion, and
verify navigation occurs to the configured URL.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: baaff14b-c72d-4771-bcd4-a66b48cf264f

📥 Commits

Reviewing files that changed from the base of the PR and between 5a7cc88 and 0ab43f3.

📒 Files selected for processing (3)
  • packages/react/src/components/presentation/auth/SignUp/BaseSignUp.tsx
  • packages/react/src/components/presentation/auth/SignUp/SignUp.tsx
  • packages/react/src/components/presentation/auth/SignUp/__tests__/SignUp.test.tsx

A completed sign-up carrying an assertion skipped the afterSignUpUrl redirect,
on the grounds that the caller had handled navigation. Consumers that pass
afterSignUpUrl and no onComplete, such as the Gate sign-up page, therefore had
nothing navigate for them: the finished step stayed on screen with its submit
action live, and clicking it started a new sign-up flow. SignIn has no such
guard and always navigates on completion.

Honour afterSignUpUrl for these completions too. shouldRedirectAfterSignUp
remains the opt-out for consumers that navigate themselves, and one that passes
no afterSignUpUrl is still never redirected.

Also latch the completion in BaseSignUp so the step rendered while the redirect
is in flight cannot be submitted again. The execution id is spent by then, and
re-submitting would begin a fresh flow.

Refs thunder-id/thunderid#4795
@ZiyamSanthosh
ZiyamSanthosh force-pushed the fix/4795-signup-completion-leaves-flow branch from 0ab43f3 to 4a57ca8 Compare August 11, 2026 10:38
@ZiyamSanthosh

Copy link
Copy Markdown
Contributor Author

Thanks — valid catch, fixed in 4a57ca8.

You were right that the existing tests disabled redirects and never executed the changed branch. I had claimed in the PR description that the redirect was untestable because these tests run in a real browser and assigning window.location.href would navigate the test page away. That was too quick a conclusion.

A URL differing from the current one only by its fragment is a same-document navigation: location updates and no reload happens, so the assignment is observable from inside the test. The new test points afterSignUpUrl at ${window.location.origin}${window.location.pathname}#signed-up, submits an assertion-bearing non-redirection completion with shouldRedirectAfterSignUp={true}, and asserts window.location.hash.

I verified it actually discriminates rather than just passing: with the !(response as any)?.assertion guard restored, the test fails; with the fix in place it passes. Full package suite is 67 tests green, typecheck and prettier clean.

I have updated the PR description to drop the claim that this branch could not be covered.

@ThaminduDilshan
ThaminduDilshan merged commit 60577d3 into thunder-id:main Aug 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants